#
# TODOS: don't productize this spike.
#
# figure out why it's denying access too often (the app engine forgets about who I am inbetween restarts of firefox, even more often locally).  Is this just cause I haven't logged into
# the local app?  looks like logging in is necessary to have it remember our choice to allow it access. if we then return it'll remember our choice. if we deny it access, we'll still be
# logged in locally, but have no access.\
#
# Therefore - force them to log into my app, then have them authorize me using the calendar.
#
# Could handle events running multiple days - right now just add it in where it starts.

try: 
  from xml.etree import ElementTree
except ImportError:  
  from elementtree import ElementTree

import gdata.calendar
import gdata.calendar.service
import gdata.service
import atom.service
import gdata.alt.appengine
import atom
import atom.url
import wsgiref.handlers
import cgi
import urllib
from dateparser import *


from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.api import users

from timedisplayer import * 

# TODO: break this out
import os

port = os.environ['SERVER_PORT']
if port and port != '80':
  HOST_NAME = '%s:%s' % (os.environ['SERVER_NAME'], port)
else:
  HOST_NAME = os.environ['SERVER_NAME']
  
  
class InitialPage(webapp.RequestHandler):

  def get(self):
    self.response.out.write("<html><body>")
    self.handleRequest()
    self.response.out.write("</body></html>")
    
  def handleRequest(self):
    
    user = users.get_current_user()
    self.forward_to_url = atom.url.Url('http', HOST_NAME, path='/loginFromGoogle')
    
    # Bail early if the user is not signed in
    if not user:
      self.createSignInLink(users)
      return
    
    # Always create a sign-out link
    self.createSignOutLink(users)
      
    self.calendarClient = gdata.calendar.service.CalendarService()

    gdata.alt.appengine.run_on_appengine(self.calendarClient)
    
    session_token = None
    # Find the AuthSub token and upgrade it to a session token.
    auth_token = gdata.auth.extract_auth_sub_token_from_url(self.request.uri)
    if auth_token:
      # Upgrade the single-use AuthSub token to a multi-use session token.
      try:
        session_token = self.calendarClient.upgrade_to_session_token(auth_token)
      except gdata.service.RequestError, request_error:
        self.promptForAccessToCalendarService("error accessing session token")
           
    if session_token:
      # If there is a current user, store the token in the datastore and
      # associate it with the current user. Since we told the client to
      # run_on_appengine, the add_token call will automatically store the
      # session token if there is a current_user.
      self.calendarClient.token_store.add_token(session_token)
      
      
      # NOTE: if there's no session token, it looks like it's still allowing our session access to go forward (bug?) when logged in.
      # Looks like we can just go ahead and use the service, since we're already signed into google? (and otherwise it'll throw an exception when we try to use the svc)

    self.processCall()
    
  def promptForAccessToCalendarService(self, errorMessage="error accessing calendar service"):
      next = self.request.uri
      auth_sub_url = self.calendarClient.GenerateAuthSubURL(self.forward_to_url, ('http://www.google.com/calendar/feeds/', ), secure=False, session=True)
      self.response.out.write('<a href="%s">' % (auth_sub_url))
      self.response.out.write(errorMessage)
      self.response.out.write("</a><br/>")

  def createSignInLink(self, users):
      return self.response.out.write('<a href="%s">Sign In</a><br>' % (users.create_login_url(str(self.forward_to_url))))

  def createSignOutLink(self, users):
      return self.response.out.write('<a href="%s">Sign Out</a><br>' % (users.create_logout_url(str(self.forward_to_url))))
      
  def processCall(self):

    try:
      timeDisplayer = TimeDisplayer(self.request, self.response, self.calendarClient)
      timeDisplayer.processCall()
        
    except gdata.service.RequestError, request_error:
      if request_error[0]['status'] == 401:
        self.promptForAccessToCalendarService()
      else:
        self.response.out.write(
            'Something else went wrong, here is the error object: %s ' % (
                str(request_error[0])))

  
application = webapp.WSGIApplication(
                                     [('/.*', InitialPage)],
                                     debug=True)

def main():
  run_wsgi_app(application)

if __name__ == "__main__":
  main()
